home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 081-090 / amok87 / hanoi / hanoi.mod < prev    next >
Text File  |  1993-11-04  |  8KB  |  184 lines

  1. MODULE Hanoi;
  2.  
  3. (* ------------------------ *)
  4. (* (c) by Roger Meyer, 1992 *)
  5. (* ------------------------ *)
  6.  
  7. IMPORT
  8.   G : DHanoi,              (* Displayroutinen      *)
  9.   S : Stacks,              (* Stack-Verwaltung     *)
  10.   E : Exec,                (* OS: Task/Mem-Manager *)
  11.   D : Dos,                 (* OS: Dos              *)
  12.       NoGuruRq;            (* Oberon: verhindert   *)
  13.                            (*      Systemabstuerze *)
  14.  
  15. CONST
  16.   Depth   = 9;                        (* Anzahl Scheiben                    *)
  17.  
  18. TYPE
  19.   DiskPtr = POINTER TO Disk;          (* Pointertyp                         *)
  20.   Disk    = RECORD(S.Node);           (* Disk: vererbt Eigenschaften von    *)
  21.               Number : INTEGER;       (* Stacks.Node.                       *)
  22.             END;                      (* Number: Breite der Scheibe         *)
  23.  
  24. VAR
  25.   Tower : ARRAY 3 OF S.StackPtr;      (* Drei Tuerme                        *)
  26.   DS    : INTEGER;                    (* Dummy INTEGER                      *)
  27.  
  28.  
  29. CONST
  30.   Height    = 1;                      (* Hoehe der Scheiben = Height+1 Pkte *)
  31.  
  32.   HStep     = Height+2;               (* Zwischenraum = 1 Pkt               *)
  33.   Step      = Height*2+2;             (* Breitenzuwachs pro Scheibe         *)
  34.   VStep     = 2*(Depth+2)*Step;       (* Zwischenraum Stick-Stick           *)
  35.   Base      = Depth*HStep+10;         (* Basislinie                         *)
  36.   WinWidth  = VStep*3+4*Step;         (* Breite der Ausgabe                 *)
  37.   WinHeight = Base+20;                (* Hoehe der Ausgabe                  *)
  38.  
  39.   StOne     = VStep DIV 2;            (* Standort erster Stick              *)
  40.   StTwo     = StOne+VStep;            (*     "    zweiter  "                *)
  41.   StThree   = StOne+VStep*2;          (*     "    dritter  "                *)
  42.  
  43.  
  44. PROCEDURE Display;                    (* Ausgabe der aktuellen Situation    *)
  45.  
  46. PROCEDURE DisplayStick(Stick : INTEGER);    (* Ausgabe eines Sticks         *)
  47.  
  48. VAR
  49.   N      : S.NodePtr;                 (* N: Zwischenspeicher                *)
  50.   Z,C    : INTEGER;                   (* Z: Anz Scheiben auf einem Stick    *)
  51.                                       (* C: Counter                         *)
  52.   x,y,h  : INTEGER;                   (* x: X-Pos des Scheibenlochs         *)
  53.                                       (* y: Y-Pos des Scheibenlochs         *)
  54.                                       (* h: Radius der Scheibe              *)
  55.   Centre : INTEGER;                   (* Centre: Mitte des Sticks           *)
  56.  
  57. BEGIN
  58.   CASE Stick OF                       (* Standort des Sticks ermitteln      *)
  59.     0 : Centre := StOne;              (* |                                  *)
  60.   | 1 : Centre := StTwo;              (* |                                  *)
  61.   | 2 : Centre := StThree;            (* |                                  *)
  62.   END;                                (* |                                  *)
  63.  
  64.   Z := S.NumberOfNodes(Tower[Stick]); (* Anzahl der Scheiben auf dem Stick  *)
  65.   C := 0;                             (* Zaehler initialisieren             *)
  66.  
  67.   WHILE C<Z DO                        (** Schleife 1 **)
  68.  
  69.     N := S.GetNodeNum(Tower[Stick],Z-(C+1)); (* Node Nummer Z-(C+1) merken  *)
  70.     h := N^(Disk).Number*Step;        (* Lok. Type Guard: Groesse des Stick *)
  71.                                       (* auslesen und Breite berechnen      *)
  72.     y := Base-C*HStep;                (* Hoehe ueber der Basis berechnen    *)
  73.     G.FillRectangle(Centre-h,y-Height,Centre+h,y); (* Scheibe zeichnen      *)
  74.     INC(C);                           (* Zaehler erhoehen                   *)
  75.  
  76.   END;                                (** Ende Schleife 1, wenn letzte **)
  77.                                       (** Scheibe dargestellt          **)
  78.  
  79. END DisplayStick;
  80.  
  81. BEGIN
  82.   G.ClearScreen();                    (* Bild loeschen                      *)
  83.  
  84.   DisplayStick(0);                    (* Sticks darstellen                  *)
  85.   DisplayStick(1);                    (* |                                  *)
  86.   DisplayStick(2);                    (* |                                  *)
  87.  
  88.   D.Delay(5);                         (* 5/50 sec warten                    *)
  89.  
  90. END Display;
  91.  
  92.  
  93. PROCEDURE InitTower;                  (* Programm Initialisieren            *)
  94.  
  95. VAR
  96.   Count   : INTEGER;                  (* Zaehler                            *)
  97.   TheDisk : DiskPtr;                  (* Temporaere Scheibe                 *)
  98.  
  99. BEGIN
  100.   Tower[0] := S.NewStack();           (* Stacks neu anlegen                 *)
  101.   Tower[1] := S.NewStack();           (* |                                  *)
  102.   Tower[2] := S.NewStack();           (* |                                  *)
  103.  
  104.   Count := 0;                         (* Counter initialisieren             *)
  105.  
  106.   WHILE Count<Depth DO                (** Schleife 1 **)
  107.  
  108.     NEW(TheDisk);                     (* Neue Scheibe                       *)
  109.     TheDisk.Number := Depth-Count;    (* Groesse setzen                     *)
  110.     S.Put(Tower[0],TheDisk);          (* Auf den Stack legen                *)
  111.     INC(Count);                       (* Counter erhoehen                   *)
  112.  
  113.   END;                                (** Ende Schleife 1, wenn letzte     **)
  114.                                       (** Scheibe initialisiert            **)
  115.  
  116.   G.SetGraphMode(WinWidth,WinHeight); (* Ausgabe initialisieren             *)
  117.  
  118. END InitTower;
  119.  
  120.  
  121. PROCEDURE CleanUp;                    (* Aufraeumen                         *)
  122.  
  123. BEGIN
  124.   S.DisposeStack(Tower[0]);           (* Stacks loeschen                    *)
  125.   S.DisposeStack(Tower[1]);           (* |                                  *)
  126.   S.DisposeStack(Tower[2]);           (* GarbageCollector fuer die Scheiben *)
  127.  
  128.   G.EndGraphMode;                     (* Graphik abschalten                 *)
  129.  
  130. END CleanUp;
  131.  
  132.  
  133. PROCEDURE WhichStack(from,to : INTEGER):INTEGER; (* Stack ermitteln         *)
  134.  
  135. VAR
  136.   S : SET;
  137.  
  138. BEGIN
  139.   S := -{from,to};                    (* Umkehrmenge von {from,to}          *)
  140.   IF 0 IN S THEN RETURN 0 END;        (* Uebrig bleibt der Stack fuer die   *)
  141.   IF 1 IN S THEN RETURN 1 END;        (* die Verschiebung                   *)
  142.   IF 2 IN S THEN RETURN 2 END;        (* |                                  *)
  143.  
  144. END WhichStack;
  145.  
  146.  
  147. PROCEDURE Move(from,to,anz : INTEGER); (* Scheiben von from nach to         *)
  148.                                        (* verschieben                       *)
  149.  
  150. VAR
  151.   TheStack : INTEGER;                  (* Nummer des Zwischen-Stacks        *)
  152.  
  153. BEGIN
  154.   CASE anz OF                          (* Wenn ...                          *)
  155.     0 : RETURN;                        (* ... anz=0 => mache nichts         *)
  156.                                        (*     (Wir sind am Boden)           *)
  157.   | 1 : S.Put(Tower[to],S.Get(Tower[from]));
  158.                                        (* ... anz=1 => Scheibe verschieben  *)
  159.         Display;                       (*     und Situation ausgeben        *)
  160.   ELSE
  161.     TheStack := WhichStack(from,to);   (* ... sonst => Ermittle 'freier'    *)
  162.                                        (*     Stack                         *)
  163.     Move(from,TheStack,anz-1);         (*     Verschiebe alle ausser den    *)
  164.                                        (*     letzten auf den ZwSpeicher    *)
  165.     Move(from,to,1);                   (*     Groesste Scheibe verschieben  *)
  166.     Move(TheStack,to,anz-1);           (*     ZwSpeicher auf das Ziel       *)
  167.  
  168.   END;
  169.  
  170. END Move;
  171.  
  172.  
  173. BEGIN
  174.   InitTower;                           (* 'Towers' initialisieren           *)
  175.   DS := E.SetTaskPri(E.FindTask(NIL),-5);
  176.                                        (* OS: TaskPrioritaet erniedrigeren  *)
  177.   Move(0,2,Depth);                     (* Versch. alle Scheiben von 0 => 2  *)
  178.  
  179. CLOSE                                  (* Der folgende Code wird unter      *)
  180.                                        (* allen Umstaenden ausgefuehrt      *)
  181.   CleanUp;                             (* Spielzeug wieder einpacken        *)
  182.  
  183. END Hanoi.
  184.